package com.gwd.task.services.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.date.DateTime;
import com.gwd.task.entity.TaskEntity;
import com.gwd.task.enums.VersionEnum;
import com.gwd.task.exception.DataException;
import com.gwd.task.model.*;
import com.gwd.task.repository.TaskRepository;
import com.gwd.task.services.*;
import com.gwd.task.untils.ListPredicate;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author zhiyongming
 * @date 2020/11/9 10:07
 */
@Service
public class TaskServerImpl implements TaskServer {

    @Resource
    private final TaskRepository taskRepository;
    @Resource
    private ProjectServer projectServer;
    @Resource
    private ProjectNumServer projectNumServer;
    @Resource
    private UserServer userServer;
    @Resource
    private CodeSubmitRecordServer codeSubmitRecordServer;
    @Resource
    private ProjectModuleServer projectModuleServer;
    @Resource
    private TaskProcessServer taskProcessServer;

    private static final Integer UN_START = 0; //未启动
    private static final Integer START = 1;    //启动中
    private static final Integer FINISH = 2;   //已完成
    private static final Integer BLOCK = 3;    //阻塞中
    private static final Integer CANCEL = 4;   //取消
    private static final Integer TEST = 5;     //测试阶段
    private static final Integer CODE_SUBMIT = 6;     //测试阶段


    public TaskServerImpl(TaskRepository taskRepository) {
        this.taskRepository = taskRepository;
    }

    public PageUtils findByPage(TaskDTO dto, PageUtils pageUtils) {

        Page<TaskEntity> page = taskRepository.findAll((Specification<TaskEntity>)
                (root, query, cb) ->
                        ListPredicate.of(root, query, cb)
                                .equal("projectId", dto.getProjectId())
                                .equal("group", dto.getGroup()) //组别
                                .equal("devPerson", dto.getDevPerson()) //开发负责人
                                .equal("completeVersion", dto.getCompleteVersion()) //计划完成版本
                                .equal("status", dto.getStatus())
                                .like("decomposition", dto.getDecomposition()) //描述
                                .inNumber("status", dto.getStatusList(),null)
                                .finish()
                                .getRestriction(),
                pageUtils.convert("taskId", "desc"));

        List<TaskDTO> list = page.get().map(TaskDTO::new).collect(Collectors.toList());

        //匹配项目名称
        List<ProjectDTO> projectDTOList = projectServer.findAll();
        list.forEach(task -> projectDTOList.forEach(project -> {
            if (task.getProjectId().equals(project.getProjectId())) {
                task.setProjectName(project.getProjectName());
            }
        }));

        //匹配模块名称
        List<ProjectModuleDTO> projectModuleDTOS = projectModuleServer.findAll();
        list.forEach(task -> projectModuleDTOS.forEach(module -> {
            if (task.getModuleId()[0].equals(module.getModuleId())) {
                task.setLv1ModuleName(module.getModuleName());
            }
            if (task.getModuleId()[1].equals(module.getModuleId())) {
                task.setLv2ModuleName(module.getModuleName());
            }
        }));

        //匹配用户名称
        List<UserDTO> userDTOList = userServer.findAll();
        list.forEach(task -> userDTOList.forEach(user -> {
            if (task.getDevPerson().equals(user.getUserId())) {
                task.setDevPersonName(user.getUserName());
            }
            if (task.getTestPerson().equals(user.getUserId())) {
                task.setTestPersonName(user.getUserName());
            }
        }));

        //匹配版本信息
        VersionEnum[] values = VersionEnum.values();
        list.forEach(task -> Arrays.stream(values).forEach(versionEnum -> {
            if (task.getCompleteVersion().equals(versionEnum.getId())) {
                task.setCompleteVersionName(versionEnum.getVersion());
            }
        }));

        //匹配process
        List<Long> taskIds = list.stream().map(TaskDTO::getTaskId).collect(Collectors.toList());
        List<TaskProcessDTO> taskProcessDTOS = taskProcessServer.findByTaskIdList(taskIds);
        list.forEach(task -> taskProcessDTOS.forEach(process -> {
            if (task.getTaskId().equals(process.getTaskId())) {
                task.addProcess(process);
            }
        }));

        pageUtils.convert(page).setContent(list);

        return pageUtils;
    }

    @Override
    public List<TaskDTO> findByModuleIdList(List<Long> ids) {
        return taskRepository.findByLv2ModuleIdIn(ids).stream().map(TaskDTO::new).collect(Collectors.toList());
    }

    @Override
    public List<TaskDTO> findAllById(List<Long> ids) {
        return taskRepository.findAllById(ids).stream().map(TaskDTO::new).collect(Collectors.toList());
    }

    @Override
    public TaskDTO findById(Long taskId) {
        return taskRepository.findById(taskId).map(TaskDTO::new).orElse(null);
    }

    @Override
    public List<TaskDTO> findByUserIdListAndUnClose(List<Long> ids) {
        List<Integer> status = new ArrayList<>();
        status.add(UN_START);
        status.add(FINISH);
        status.add(CANCEL);
        return taskRepository.findByDevPersonInAndStatusIsNotIn(ids, status).stream().map(TaskDTO::new).collect(Collectors.toList());
    }

    @Override
    public TaskDTO start(Long taskId, Long userId) {
        Optional<TaskEntity> entity = taskRepository.findById(taskId);
        if (entity.isPresent()) {
            TaskEntity e = entity.get();
            e.setStatus(START);
            //分配编号
            e.setTaskCode(projectNumServer.getTask(e.getProjectId()));
            taskRepository.save(e);
            taskProcessServer.save(TaskProcessDTO.START(userId, taskId));
            return new TaskDTO(e);
        } else {
            return null;
        }
    }

    @Override
    public void reStart(Long taskId, Long userId) {
        Optional<TaskEntity> entity = taskRepository.findById(taskId);
        entity.ifPresent(task -> {
            task.setStatus(START);
            taskRepository.save(task);

            taskProcessServer.save(TaskProcessDTO.RESTART(userId, taskId));
        });
    }

    @Override
    public void submit(Long taskId, Long userId, CodeSubmitRecordDTO csrDTO) {
        Optional<TaskEntity> entity = taskRepository.findById(taskId);
        entity.ifPresent(e -> {
            e.setStatus(CODE_SUBMIT);
            taskRepository.save(e);

            taskProcessServer.save(TaskProcessDTO.SUBMIT(userId, taskId));


            //保存至提交记录中
            csrDTO.setCode(e.getTaskCode());
            csrDTO.setSubmitUser(userId);
            csrDTO.setSubmitTime(DateTime.now().toStringDefaultTimeZone());
            csrDTO.setProjectId(e.getProjectId());
            csrDTO.setLv1ModuleId(e.getLv1ModuleId());
            csrDTO.setLv2ModuleId(e.getLv2ModuleId());
            csrDTO.setDescribe(e.getDescribe());
            csrDTO.setRelateId(e.getTaskId());
            csrDTO.setType(0); //任务

            codeSubmitRecordServer.save(csrDTO);
        });
    }

    @Override
    public void test(Long taskId, Long userId) {
        Optional<TaskEntity> entity = taskRepository.findById(taskId);
        entity.ifPresent(task -> {
            task.setStatus(TEST);
            taskRepository.save(task);

            taskProcessServer.save(TaskProcessDTO.TEST(userId, taskId));
        });
    }

    @Override
    public void finish(Long taskId, Long userId) {
        Optional<TaskEntity> entity = taskRepository.findById(taskId);
        entity.ifPresent(task -> {
            task.setStatus(FINISH);
            taskRepository.save(task);

            taskProcessServer.save(TaskProcessDTO.FINISH(userId, taskId));
        });
    }

    @Override
    public void cancel(Long taskId, Long userId) {
        Optional<TaskEntity> entity = taskRepository.findById(taskId);
        entity.ifPresent(task -> {
            task.setStatus(CANCEL);
            taskRepository.save(task);

            taskProcessServer.save(TaskProcessDTO.CANCEL(userId, taskId));
        });
    }

    @Override
    public void block(Long taskId, Long userId, String describe) {
        Optional<TaskEntity> entity = taskRepository.findById(taskId);
        entity.ifPresent(task -> {
            task.setStatus(BLOCK);
            taskRepository.save(task);

            taskProcessServer.save(TaskProcessDTO.BLOCK(userId, taskId, describe));
        });
    }

    @Override
    public void save(TaskDTO dto, Long id) {
        TaskEntity save;
        if (dto.getTaskId()!=null) {
            Optional<TaskEntity> entity = taskRepository.findById(dto.getTaskId());
            if (!entity.isPresent()) {
                throw new DataException("TaskId:" + dto.getTaskId() + " 对应的数据不存在.");
            }
            save = entity.get();
        } else {
            save = new TaskEntity();
        }
        BeanUtil.copyProperties(dto, save, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
        save.setLv1ModuleId(dto.getModuleId()[0]);
        save.setLv2ModuleId(dto.getModuleId()[1]);

        TaskEntity entity = taskRepository.save(save);

        //新增操作日志
        if (dto.getTaskId() == null) {
            taskProcessServer.save(TaskProcessDTO.CREATE(id, entity.getTaskId()));
        }
    }

    @Override
    public void remove(Long id) {
        taskRepository.deleteById(id);
    }

    @Override
    public void board(List<Long> ids) {
        taskRepository.saveAll(taskRepository.findAllById(ids).stream().peek(e-> e.setStatus(TEST)).collect(Collectors.toList()));
    }
}
